package com.alatus.config.filter;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.Result;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import com.alatus.result.CodeEnum;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
public class TokenVerifyFilter extends OncePerRequestFilter {

    @Resource
    private RedisService redisService;
//    @Resource
//    //    springboot框架提供的线程池,ioc容器内已经存在
//    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getRequestURI().equals(Constants.LOGIN_URI)) { //如果是登录请求，此时还没有生成jwt，那不需要对登录请求进行jwt验证
            //验证jwt通过了 ，让Filter链继续执行，也就是继续执行下一个Filter
            filterChain.doFilter(request, response);
        } else {
            String token;
            if(request.getRequestURI().equals(Constants.EXPORT_EXCEL_URI)){
                token = request.getParameter(Constants.TOKEN_NAME);
            }
            else{
                token = request.getHeader(Constants.TOKEN_NAME);
            }
            if(!StringUtils.hasText(token)){
//                没拿到token,将失败这个枚举传回去,解析并取出常量拼接
                Result result = Result.FAIL(CodeEnum.TOKEN_IS_EMPTY);
//                封装
                String resultJSON = JSONUtils.toJSON(result);
//                返回
                ResponseUtils.write(response,resultJSON);
                return;
            }
//            验证token有没有被篡改过,也是验证token合法性
            if (!(JWTUtils.verifyJWT(token))){
//                token不合法
                Result result = Result.FAIL(CodeEnum.TOKEN_IS_NONE_MATCH);
//                封装
                String resultJSON = JSONUtils.toJSON(result);
//                返回
                ResponseUtils.write(response,resultJSON);
                return;
            }
            TUser tUser = JWTUtils.parseUserFromJWT(token);
            String redisToken = (String) redisService.getValue(Constants.REDIS_JWT_KEY + tUser.getId());
            if(!StringUtils.hasText(redisToken)){
//                没有获取到内容说明token过期了
                Result fail = Result.FAIL(CodeEnum.TOKEN_IS_EXPIRED);
                String json = JSONUtils.toJSON(fail);
                ResponseUtils.write(response,json);
                return;
            }
            if (!redisToken.equals(token)) {
//                登陆失败token错误
                Result result = Result.FAIL(CodeEnum.TOKEN_IS_ERROR);
//                把R对象转为JSON
                String json = JSONUtils.toJSON(result);
                ResponseUtils.write(response,json);
                return;
            }
//            jwt验证通过了
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser,tUser.getLoginPwd(),tUser.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
//            刷新一下token
//            做异步执行
//            new Thread(new Runnable() {
//                @Override
//                public void run() {
////                    这里刷新token即可
////                    从请求头中获取
//                    String rememberMe = request.getHeader("rememberMe");
//                    if (!Boolean.parseBoolean(rememberMe)) {
//                        redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);
//                    }
//                }
//            }).start();
//            最好使用线程池的方式去执行
//            threadPoolTaskExecutor.execute(() -> {
//                    这里刷新token即可
//                    从请求头中获取
//                    String rememberMe = null;
//                    if(StringUtils.hasText(request.getHeader(Constants.REMEMBER_ME))){
//                        rememberMe = request.getHeader(Constants.REMEMBER_ME);
//                    }
//                    if (!Boolean.parseBoolean(rememberMe)) {
//                        redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);
//                    }
//            });
//            验证jwt通过了,让filter链继续执行


//            经过实验,线程池有概率导致请求和我们的service走的线程不是同一个导致请求头里面获取这个rememberMe报错
//            还是不用线程为好,慢点就慢点吧
            String rememberMe = null;
            if(StringUtils.hasText(request.getHeader(Constants.REMEMBER_ME))){
                rememberMe = request.getHeader(Constants.REMEMBER_ME);
            }
            if (!Boolean.parseBoolean(rememberMe)) {
                redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);
            }
            filterChain.doFilter(request,response);
        }
    }
}
